﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
//Adittional
using DO.Domain.Repositories;
using DO.Common.Messages;
using DO.Domain.AppServices;

namespace DO.Domain.TransManager
{
    public abstract class TransManagerBase : ITransManager
    {
        protected bool IsInTransaction;

        public IRepositoryLocator RepositoryLocator { get; set; }

        #region ITransManager Members

        public TResult ExecuteCommand<TResult>(Func<IRepositoryLocator, TResult> command)
           where TResult : class, Common.Messages.IResponseDTOEnvelop
        {
            try
            {
                BeginTransaction();
                var result = command.Invoke(this.RepositoryLocator);
                CommitTransaction();
                CheckForWarnings(result);
                return result;
            }
            catch (BusinessException exception)
            {
                if (this.IsInTransaction)
                {
                    RollbackTransaction();
                }

                var type = typeof(TResult);
                var instance = Activator.CreateInstance(type, true) as IResponseDTOEnvelop;

                if (instance != null)
                {
                    instance.Response.AddBusinessException(exception);
                }

                return instance as TResult;
            }
            catch (Exception e)
            {
                throw;
            }
        }

        public virtual void BeginTransaction()
        {
            this.IsInTransaction = true;
            return;
        }

        public void CommitTransaction()
        {
            this.IsInTransaction = false;
            return;
        }

        public void RollbackTransaction()
        {
            this.IsInTransaction = false;
            return;
        }

        #endregion

        #region IDisposable Members

        public void Dispose()
        {
            Dispose(true);
            GC.SuppressFinalize(this);
        }

        protected bool IsDisposed = false;

        protected virtual void Dispose(bool isDisposing)
        {
            if (!isDisposing)
            {
                return;
            }

            if (!this.IsDisposed && this.IsInTransaction)
            {
                this.RollbackTransaction();
            }

            this.RepositoryLocator = null;
            this.IsDisposed = true;
        }

        #endregion

        #region Helper methods

        private void CheckForWarnings<TResult>(TResult result)
        {
            var response = result as IResponseDTOEnvelop;

            if (response == null)
                return;

            var notifier = Container.RequestContext.BusinessNotifier;

            if (notifier.HasWarnings)
                response.Response.AddBussinessWarnings(notifier.RetrieveWarnings());
        }
        #endregion
    }
}
